package de.westranger.forex.trading.genetic.allel;

import java.text.ParseException;
import java.util.Stack;

import de.westranger.forex.trading.genetic.allel.operator.CompareOperator;
import de.westranger.forex.trading.genetic.allel.operator.CompareOperatorType;
import de.westranger.forex.trading.genetic.allel.operator.EvaluateTerminal;
import de.westranger.forex.trading.genetic.allel.operator.EvaluateTerminalSymbol;
import de.westranger.forex.trading.genetic.allel.operator.LogicalOperator;
import de.westranger.forex.trading.genetic.allel.operator.LogicalOperatorType;
import de.westranger.forex.trading.genetic.allel.operator.Terminal;
import de.westranger.forex.trading.genetic.allel.operator.TerminalSymbol;

public final class ChromosomPrinter {
	private final Stack<Node> nodeList;
	private final Stack<String> edgeList;
	private final static String PREFIX = "node";
	
	public ChromosomPrinter(){
		this.nodeList = new Stack<Node>();
		this.edgeList = new Stack<String>();
	}
	
	public String generateGraphVIZ(final Node node){
		nodeList.clear();
		edgeList.clear();

		final StringBuilder strBld = new StringBuilder();
		this.addNode(node);
		
		strBld.append("digraph G {\n");
		
		for(final Node ndStr:nodeList){
			strBld.append('\t');
			strBld.append(PREFIX);
			strBld.append(getID(ndStr));
			strBld.append(" [label=\"");
			try{
				if(ndStr instanceof LogicalOperator){
					strBld.append(LogicalOperatorType.parse(ndStr.getValue()).name());
				}else if(ndStr instanceof CompareOperator){
					strBld.append(CompareOperatorType.parse(ndStr.getValue()).name());
				}else if(ndStr instanceof Terminal){
					strBld.append(TerminalSymbol.parse(ndStr.getValue()).name());
				}else if(ndStr instanceof EvaluateTerminal){
					strBld.append("eval(");
					strBld.append(EvaluateTerminalSymbol.parse(ndStr.getValue()).name());
					strBld.append(')');
				}
			}catch(ParseException pe){
				pe.printStackTrace();
			}
			strBld.append("\"];\n");
		}

		for(final String str:edgeList){
			strBld.append('\t');
			strBld.append(str);
			strBld.append('\n');
		}

		strBld.append('}');
		
		return strBld.toString();
	}
	
	private void addNode(final Node node){
		node.toString();
		this.nodeList.add(node);
		if(node.getLeftChild() != null){
			edgeList.add(PREFIX + getID(node) +" -> " +PREFIX + getID(node.getLeftChild()));
			this.addNode(node.getLeftChild());
		}

		if(node.getRightChild() != null){
			edgeList.add(PREFIX + getID(node) +" -> " + PREFIX + getID(node.getRightChild()));
			this.addNode(node.getRightChild());
		}
	}
	
	private String getID(final Node node){
		return Integer.toHexString(System.identityHashCode(node));
	}
}
